// DMSpinButtonCtrl.cpp: implementation of the CDMSpinButtonCtrl class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "bcgcbpro.h"

#if defined (_BCGPCALENDAR_STANDALONE)
	#include "BCGPCalendarVisualManager.h"
	#define visualManager	CBCGPCalendarVisualManager::GetInstance ()
#elif defined (_BCGPGRID_STANDALONE)
	#include "BCGPGridVisualManager.h"
	#define visualManager	CBCGPGridVisualManager::GetInstance ()
#else
	#include "BCGPVisualManager.h"
	#define visualManager	CBCGPVisualManager::GetInstance ()
#endif

#include "BCGGlobals.h"
#include "DMSpinButtonCtrl.h"
#include "BCGPToolBarImages.h"
#include "BCGPDrawManager.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CDMSpinButtonCtrl

CDMSpinButtonCtrl::CDMSpinButtonCtrl(CGeoProp* pProp)
{
	m_bTracked = FALSE;

	m_bIsButtonPressedUp = FALSE;
	m_bIsButtonPressedDown = FALSE;

	m_bIsButtonHighligtedUp = FALSE;
	m_bIsButtonHighligtedDown = FALSE;

	m_pProp = pProp;
}
//*****************************************************************************************
CDMSpinButtonCtrl::~CDMSpinButtonCtrl()
{
}

BEGIN_MESSAGE_MAP(CDMSpinButtonCtrl, CNumSpinCtrl)
	//{{AFX_MSG_MAP(CDMSpinButtonCtrl)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_CANCELMODE()
	ON_WM_MOUSEMOVE()
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
	ON_WM_VSCROLL_REFLECT()
	ON_WM_MOUSEWHEEL()

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDMSpinButtonCtrl message handlers

void CDMSpinButtonCtrl::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	CBCGPMemDC memDC (dc, this);

	OnDraw (&memDC.GetDC ());
}
//*****************************************************************************************
void CDMSpinButtonCtrl::VScroll (UINT nSBCode, UINT nPos)
{
	ASSERT_VALID (m_pProp);
	
	m_pProp->OnUpdateValue ();
}
BOOL CDMSpinButtonCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	return FALSE;
}
void CDMSpinButtonCtrl::OnDraw (CDC* pDC)
{
	ASSERT_VALID (this);
	ASSERT_VALID (pDC);

	CRect rectClient;
	GetClientRect (rectClient);

	if (CBCGPToolBarImages::m_bIsDrawOnGlass)
	{
		CBCGPDrawManager dm (*pDC);
		dm.DrawRect (rectClient, globalData.clrWindow, (COLORREF)-1);
	}
	else
	{
		pDC->FillRect (rectClient, &globalData.brWindow);
	}

	int nState = 0;

	if (m_bIsButtonPressedUp)
	{
		nState |= SPIN_PRESSEDUP;
	}

	if (m_bIsButtonPressedDown)
	{
		nState |= SPIN_PRESSEDDOWN;
	}

	if (m_bIsButtonHighligtedUp)
	{
		nState |= SPIN_HIGHLIGHTEDUP;
	}

	if (m_bIsButtonHighligtedDown)
	{
		nState |= SPIN_HIGHLIGHTEDDOWN;
	}

	if (!IsWindowEnabled ())
	{
		nState |= SPIN_DISABLED;
	}

	visualManager->OnDrawSpinButtons (
		pDC, rectClient, nState, FALSE, (CBCGPSpinButtonCtrl*)this);
}
//*****************************************************************************************
void CDMSpinButtonCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CRect rect;
	GetClientRect (rect);

	CRect rectUp = rect;
	rectUp.bottom = rect.CenterPoint ().y;

	CRect rectDown = rect;
	rectDown.top = rectUp.bottom;

	m_bIsButtonPressedUp = rectUp.PtInRect (point);
	m_bIsButtonPressedDown = rectDown.PtInRect (point);
	
	CNumSpinCtrl::OnLButtonDown(nFlags, point);
}
//*****************************************************************************************
void CDMSpinButtonCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
{
	m_bIsButtonPressedUp = FALSE;
	m_bIsButtonPressedDown = FALSE;
	
	m_bIsButtonHighligtedUp = FALSE;
	m_bIsButtonHighligtedDown = FALSE;

	CNumSpinCtrl::OnLButtonUp(nFlags, point);
}
//*****************************************************************************************
void CDMSpinButtonCtrl::OnCancelMode() 
{
	CNumSpinCtrl::OnCancelMode();

	m_bIsButtonPressedUp = FALSE;
	m_bIsButtonPressedDown = FALSE;

	m_bIsButtonHighligtedUp = FALSE;
	m_bIsButtonHighligtedDown = FALSE;
}
//*****************************************************************************************
void CDMSpinButtonCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	BOOL bIsButtonHighligtedUp = m_bIsButtonHighligtedUp;
	BOOL bIsButtonHighligtedDown = m_bIsButtonHighligtedDown;

	CRect rect;
	GetClientRect (rect);

	CRect rectUp = rect;
	rectUp.bottom = rect.CenterPoint ().y;

	CRect rectDown = rect;
	rectDown.top = rectUp.bottom;

	m_bIsButtonHighligtedUp = rectUp.PtInRect (point);
	m_bIsButtonHighligtedDown = rectDown.PtInRect (point);

	if (nFlags & MK_LBUTTON)
	{
		m_bIsButtonPressedUp = m_bIsButtonHighligtedUp;
		m_bIsButtonPressedDown = m_bIsButtonHighligtedDown;
	}
	
	CNumSpinCtrl::OnMouseMove(nFlags, point);

	if (bIsButtonHighligtedUp != m_bIsButtonHighligtedUp ||
		bIsButtonHighligtedDown != m_bIsButtonHighligtedDown)
	{
		RedrawWindow ();
	}

	if (!m_bTracked)
	{
		m_bTracked = TRUE;
		
		TRACKMOUSEEVENT trackmouseevent;
		trackmouseevent.cbSize = sizeof(trackmouseevent);
		trackmouseevent.dwFlags = TME_LEAVE;
		trackmouseevent.hwndTrack = GetSafeHwnd();
		trackmouseevent.dwHoverTime = HOVER_DEFAULT;
		BCGPTrackMouse (&trackmouseevent);	
	}
}
//*****************************************************************************************
LRESULT CDMSpinButtonCtrl::OnMouseLeave(WPARAM,LPARAM)
{
	m_bTracked = FALSE;

	if (m_bIsButtonPressedUp || m_bIsButtonPressedDown ||
		m_bIsButtonHighligtedUp || m_bIsButtonHighligtedDown)
	{
		m_bIsButtonHighligtedUp = FALSE;
		m_bIsButtonHighligtedDown = FALSE;

		RedrawWindow ();
	}

	return 0;
}
//*********************************************************************************
BOOL CDMSpinButtonCtrl::OnEraseBkgnd(CDC* /*pDC*/) 
{
	return TRUE;
}

//////////////////////////////////////////////////////////////////////////
VOID CALLBACK BCGPTrackMouseTimerProc (HWND hWnd, 
									   UINT /*uMsg*/,
									   UINT idEvent, 
									   DWORD /*dwTime*/)
{
	RECT	rect;
	POINT	pt;
	
	::GetClientRect (hWnd, &rect);
	::MapWindowPoints (hWnd, NULL, (LPPOINT)&rect, 2);
	
	::GetCursorPos (&pt);
	if (!::PtInRect (&rect, pt) || (WindowFromPoint(pt) != hWnd)) 
	{
		if (!::KillTimer (hWnd, idEvent))
		{
			// Error killing the timer!
		}
		
		::PostMessage (hWnd,WM_MOUSELEAVE, 0, 0);
	}
}

BOOL CDMSpinButtonCtrl::BCGPTrackMouse (LPTRACKMOUSEEVENT ptme)
{
	ASSERT (ptme != NULL);
	if (ptme->cbSize < sizeof (TRACKMOUSEEVENT))
	{
		ASSERT (FALSE);
		return FALSE;
	}
	
	if (!::IsWindow(ptme->hwndTrack)) 
	{
		ASSERT (FALSE);
		return FALSE;
	}
	
	if (!(ptme->dwFlags & TME_LEAVE)) 
	{
		ASSERT (FALSE);
		return FALSE;
	}
	
	return (BOOL) ::SetTimer (ptme->hwndTrack, ptme->dwFlags, 100,
		(TIMERPROC) BCGPTrackMouseTimerProc);
}
